﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Dubbo.Rpc
{
    public abstract class AbstractProtocol : IProtocol
    {
        //protected readonly Logger logger = LoggerFactory.getLogger(getClass());

        protected readonly ConcurrentDictionary<string, IExporter> exporterDict = new ConcurrentDictionary<string, IExporter>();

        protected readonly ConcurrentBag<IInvoker> invokers = new ConcurrentBag<IInvoker>();

        protected static string serviceKey(URL url)
        {
            //return ProtocolUtils.serviceKey(url);
            return url.ToString();
        }

        protected static string serviceKey(int port, string serviceName, string serviceVersion, string serviceGroup)
        {
            //return ProtocolUtils.serviceKey(port, serviceName, serviceVersion, serviceGroup);
            return string.Empty;
        }

        public virtual void Destroy()
        {
            for (int i = 0; i < invokers.Count; i++)
            {
                //if (invoker != null)
                //{

                //    invokers.TryTake(out invoker);
                //    try
                //    {
                //        if (logger.isInfoEnabled())
                //        {
                //            logger.info("Destroy reference: " + invoker.getUrl());
                //        }
                //        invoker.destroy();
                //    }
                //    catch (Throwable t)
                //    {
                //        logger.warn(t.getMessage(), t);
                //    }
                //}
            }
            foreach (var key in exporterDict.Keys)
            {
                IExporter exporter;
                if (exporterDict.TryRemove(key, out exporter) && exporter != null)
                {
                    try
                    {
                        //if (logger.isInfoEnabled())
                        //{
                        //    logger.info("Unexport service: " + exporter.getInvoker().getUrl());
                        //}
                        exporter.Unexport();
                    }
                    catch (Exception ex)
                    {
                        //logger.warn(t.getMessage(), t);
                    }
                }
            }
        }

        protected static int GetServerShutdownTimeout()
        {
            //int timeout = Constants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
            //string value = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY);
            //if (value != null && value.length() > 0)
            //{
            //    try
            //    {
            //        timeout = Integer.parseInt(value);
            //    }
            //    catch (Exception e)
            //    {
            //    }
            //}
            //else
            //{
            //    value = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
            //    if (value != null && value.length() > 0)
            //    {
            //        try
            //        {
            //            timeout = Integer.parseInt(value) * 1000;
            //        }
            //        catch (Exception e)
            //        {
            //        }
            //    }
            //}

            //return timeout;
            return 0;
        }

        public abstract int GetDefaultPort();

        public abstract IExporter<T> Export<T>(IInvoker<T> invoker);

        public abstract IInvoker<T> Refer<T>(URL url);
    }
}
